package com.idealighter.game.server.net.http;

import com.idealighter.utils.json.JsonUtil;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpHeaderValues;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpUtil;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.util.AsciiString;
import io.netty.util.CharsetUtil;

import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

public class ReqHttpMessage {
  private final FullHttpRequest request;
  private final ResponseBo response; // DefaultFullHttpResponse response;
  private final SessionBo session;
  private final ChannelHandlerContext ctx;

  /**
   * 构造函数.
   * 
   * @param ctx .
   * @param request .
   * @param response .
   * @param session .
   */
  public ReqHttpMessage(ChannelHandlerContext ctx, FullHttpRequest request, ResponseBo response,
      SessionBo session) {
    this.ctx = ctx;
    this.request = request;
    this.response = response;
    this.session = session;
  }

  public String getPath() {
    String url = this.request.uri();
    return url.replace(this.request.headers().get(HttpHeaderNames.HOST), "");
  }

  /**
   * 发送错误 .
   *
   * @param status http状态.
   */
  public void sendError(HttpResponseStatus status) {
    FullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status);
    httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json; charset=utf-8");
    ctx.writeAndFlush(httpResponse).addListener(ChannelFutureListener.CLOSE);
  }

  /**
   * 返回消息 .
   *
   * @param result 返回结果.
   */
  public void sendResponse(ResHttpMessage result) {
    String content = "{}";
    if (result != null) {
      content = JsonUtil.toJson(result);
    }
    FullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
        response.getStatus(), Unpooled.copiedBuffer(content, CharsetUtil.UTF_8));

    httpResponse.headers().add(WebHttpServerHandler.sessionAttr, session.getSessionId());
    httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json; charset=utf-8");
    httpResponse.headers().setInt(HttpHeaderNames.CONTENT_LENGTH,
        httpResponse.content().readableBytes());

    // 配置header
    Map<AsciiString, Object> headers = response.headers;
    for (AsciiString key : headers.keySet()) {
      httpResponse.headers().set(key, headers.get(key));
    }

    boolean keepAlive = HttpUtil.isKeepAlive(request);
    if (!keepAlive) {
      ctx.writeAndFlush(httpResponse).addListener(ChannelFutureListener.CLOSE);
    } else {
      httpResponse.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
      ctx.writeAndFlush(httpResponse);
    }
  }

  // 重定向
  public void sendRedirect(String url) {
    response.setStatus(HttpResponseStatus.FOUND);
    response.headers().put(HttpHeaderNames.LOCATION, url);
  }

  public static class ResponseBo {
    private HttpResponseStatus status = HttpResponseStatus.OK;
    private Map<AsciiString, Object> headers = new ConcurrentHashMap<AsciiString, Object>();

    public HttpResponseStatus getStatus() {
      return status;
    }

    public void setStatus(HttpResponseStatus status) {
      this.status = status;
    }

    public Map<AsciiString, Object> headers() {
      return headers;
    }
  }

  public static class SessionBo {
    private final String sessionId;
    private Map<String, Object> sessionMap = new ConcurrentHashMap<String, Object>();

    public SessionBo() {
      sessionId = UUID.randomUUID().toString().replaceAll("-", "");
    }

    public String getSessionId() {
      return sessionId;
    }

    public Object getAttribute(String name) {
      return sessionMap.get(name);
    }

    public void setAttribute(String name, Object value) {
      sessionMap.put(name, value);
    }

    public void removeAttribute(String name) {
      sessionMap.remove(name);
    }
  }

  public FullHttpRequest getRequest() {
    return request;
  }

  public ResponseBo getResponse() {
    return response;
  }

  public SessionBo getSession() {
    return session;
  }
}
